/*!
 * \file galileo_e1b_reed_solomon_test.cc
 * \brief Tests for Reed Solomon E1B encoder and decoder
 * \author Carles Fernandez-Prades, 2021. cfernandez(at)cttc.es
 *
 *
 * -----------------------------------------------------------------------------
 *
 * GNSS-SDR is a Global Navigation Satellite System software-defined receiver.
 * This file is part of GNSS-SDR.
 *
 * Copyright (C) 2010-2021  (see AUTHORS file for a list of contributors)
 * SPDX-License-Identifier: GPL-3.0-or-later
 *
 * -----------------------------------------------------------------------------
 */

#include "gnss_sdr_make_unique.h"
#include "reed_solomon.h"
#include <gtest/gtest.h>


TEST(ReedSolomonE1BTest, EncodeWithPoly)
{
    const std::vector<uint8_t> information_vector = {147, 109, 66, 23, 234, 140,
        74, 234, 49, 89, 241, 253, 169, 161, 89, 93, 75, 142, 83, 102, 98, 218,
        14, 197, 155, 151, 43, 181, 9, 163, 142, 111, 8, 118, 21, 47, 135, 139,
        108, 215, 51, 147, 185, 52, 17, 151, 97, 102, 238, 71, 83, 114, 47, 80,
        67, 199, 215, 162};
    const std::vector<uint8_t> code_vector = {147, 109, 66, 23, 234, 140, 74,
        234, 49, 89, 241, 253, 169, 161, 89, 93, 75, 142, 83, 102, 98, 218, 14,
        197, 155, 151, 43, 181, 9, 163, 142, 111, 8, 118, 21, 47, 135, 139, 108,
        215, 51, 147, 185, 52, 17, 151, 97, 102, 238, 71, 83, 114, 47, 80, 67,
        199, 215, 162, 238, 77, 12, 72, 235, 21, 148, 213, 230, 54, 183, 82, 49,
        104, 12, 228, 150, 157, 220, 112, 236, 187, 63, 31, 175, 47, 210, 164,
        17, 104, 98, 46, 252, 165, 194, 57, 26, 213, 14, 133, 176, 148, 34, 9,
        167, 43, 204, 198, 25, 164, 233, 55, 153, 31, 237, 84, 212, 76, 137,
        242};

    auto rs = std::make_unique<ReedSolomon>("E1B");

    std::vector<uint8_t> encoded_output = rs->encode_with_generator_poly(information_vector);

    EXPECT_TRUE(encoded_output == code_vector);
}


TEST(ReedSolomonE1BTest, EncodeWithCustomPoly)
{
    // ICD 2.0 Annex F
    const std::vector<uint8_t> information_vector = {147, 109, 66, 23, 234, 140,
        74, 234, 49, 89, 241, 253, 169, 161, 89, 93, 75, 142, 83, 102, 98, 218,
        14, 197, 155, 151, 43, 181, 9, 163, 142, 111, 8, 118, 21, 47, 135, 139,
        108, 215, 51, 147, 185, 52, 17, 151, 97, 102, 238, 71, 83, 114, 47, 80,
        67, 199, 215, 162};
    const std::vector<uint8_t> code_vector = {147, 109, 66, 23, 234, 140, 74,
        234, 49, 89, 241, 253, 169, 161, 89, 93, 75, 142, 83, 102, 98, 218, 14,
        197, 155, 151, 43, 181, 9, 163, 142, 111, 8, 118, 21, 47, 135, 139, 108,
        215, 51, 147, 185, 52, 17, 151, 97, 102, 238, 71, 83, 114, 47, 80, 67,
        199, 215, 162, 238, 77, 12, 72, 235, 21, 148, 213, 230, 54, 183, 82, 49,
        104, 12, 228, 150, 157, 220, 112, 236, 187, 63, 31, 175, 47, 210, 164,
        17, 104, 98, 46, 252, 165, 194, 57, 26, 213, 14, 133, 176, 148, 34, 9,
        167, 43, 204, 198, 25, 164, 233, 55, 153, 31, 237, 84, 212, 76, 137,
        242};

    // Instantiate a ReedSolomon object with Galileo E1 (INAV) parameters
    const int nroots = 60;
    const int minpoly = 29;
    const int pad = 0;
    const int prim = 1;
    const int fcr = 195;
    const int shortening = 137;
    const std::vector<uint8_t> genpoly_coeff = {1, 208, 42, 48, 76, 19, 41, 108,
        167, 235, 166, 244, 186, 18, 124, 251, 79, 193, 14, 154, 6, 118, 19, 3,
        122, 9, 187, 42, 131, 46, 66, 65, 62, 94, 101, 45, 214, 141, 131, 230,
        102, 20, 63, 202, 36, 23, 188, 88, 169, 62, 73, 88, 152, 197, 231, 58,
        101, 154, 190, 91, 193};

    auto rs = std::make_unique<ReedSolomon>(nroots, minpoly, prim, fcr, pad, shortening, genpoly_coeff);

    std::vector<uint8_t> encoded_output = rs->encode_with_generator_poly(information_vector);

    EXPECT_TRUE(encoded_output == code_vector);
}


TEST(ReedSolomonE1BTest, EncodeWithMatrix)
{
    // ICD 2.0 Annex F
    const std::vector<uint8_t> information_vector = {147, 109, 66, 23, 234, 140,
        74, 234, 49, 89, 241, 253, 169, 161, 89, 93, 75, 142, 83, 102, 98, 218,
        14, 197, 155, 151, 43, 181, 9, 163, 142, 111, 8, 118, 21, 47, 135, 139,
        108, 215, 51, 147, 185, 52, 17, 151, 97, 102, 238, 71, 83, 114, 47, 80,
        67, 199, 215, 162};
    const std::vector<uint8_t> code_vector = {147, 109, 66, 23, 234, 140, 74,
        234, 49, 89, 241, 253, 169, 161, 89, 93, 75, 142, 83, 102, 98, 218, 14,
        197, 155, 151, 43, 181, 9, 163, 142, 111, 8, 118, 21, 47, 135, 139, 108,
        215, 51, 147, 185, 52, 17, 151, 97, 102, 238, 71, 83, 114, 47, 80, 67,
        199, 215, 162, 238, 77, 12, 72, 235, 21, 148, 213, 230, 54, 183, 82, 49,
        104, 12, 228, 150, 157, 220, 112, 236, 187, 63, 31, 175, 47, 210, 164,
        17, 104, 98, 46, 252, 165, 194, 57, 26, 213, 14, 133, 176, 148, 34, 9,
        167, 43, 204, 198, 25, 164, 233, 55, 153, 31, 237, 84, 212, 76, 137,
        242};

    auto rs = std::make_unique<ReedSolomon>("E1B");

    std::vector<uint8_t> encoded_output = rs->encode_with_generator_matrix(information_vector);

    EXPECT_TRUE(code_vector == encoded_output);
}


TEST(ReedSolomonE1BTest, EncodeWithCustomMatrix)
{
    // ICD 2.0 Annex F
    const std::vector<uint8_t> information_vector = {147, 109, 66, 23, 234, 140,
        74, 234, 49, 89, 241, 253, 169, 161, 89, 93, 75, 142, 83, 102, 98, 218,
        14, 197, 155, 151, 43, 181, 9, 163, 142, 111, 8, 118, 21, 47, 135, 139,
        108, 215, 51, 147, 185, 52, 17, 151, 97, 102, 238, 71, 83, 114, 47, 80,
        67, 199, 215, 162};
    const std::vector<uint8_t> code_vector = {147, 109, 66, 23, 234, 140, 74,
        234, 49, 89, 241, 253, 169, 161, 89, 93, 75, 142, 83, 102, 98, 218, 14,
        197, 155, 151, 43, 181, 9, 163, 142, 111, 8, 118, 21, 47, 135, 139, 108,
        215, 51, 147, 185, 52, 17, 151, 97, 102, 238, 71, 83, 114, 47, 80, 67,
        199, 215, 162, 238, 77, 12, 72, 235, 21, 148, 213, 230, 54, 183, 82, 49,
        104, 12, 228, 150, 157, 220, 112, 236, 187, 63, 31, 175, 47, 210, 164,
        17, 104, 98, 46, 252, 165, 194, 57, 26, 213, 14, 133, 176, 148, 34, 9,
        167, 43, 204, 198, 25, 164, 233, 55, 153, 31, 237, 84, 212, 76, 137,
        242};

    const int nroots = 60;
    const int minpoly = 29;
    const int prim = 1;
    const int fcr = 195;
    const int pad = 0;
    const int shortening = 137;
    const std::vector<uint8_t> genpoly_coeff;
    const std::vector<std::vector<uint8_t>> genmatrix = {
        {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
        {0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
        {0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
        {0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
        {0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
        {0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
        {0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
        {0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
        {0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
        {0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
        {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
        {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
        {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
        {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
        {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
        {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
        {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
        {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
        {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
        {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
        {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
        {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
        {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
        {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
        {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
        {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
        {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
        {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
        {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
        {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
        {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
        {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
        {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
        {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
        {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
        {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
        {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
        {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
        {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
        {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
        {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
        {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
        {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
        {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
        {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
        {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
        {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
        {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
        {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0},
        {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0},
        {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0},
        {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0},
        {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0},
        {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0},
        {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0},
        {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0},
        {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0},
        {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
        {193, 146, 156, 183, 62, 35, 90, 25, 89, 208, 43, 148, 117, 199, 92, 112, 4, 70, 74, 183, 37, 100, 118, 44, 238, 107, 186, 200, 179, 63, 140, 194, 176, 131, 38, 110, 33, 178, 43, 173, 98, 96, 105, 115, 90, 76, 133, 194, 133, 182, 99, 20, 183, 90, 84, 131, 26, 139},
        {91, 221, 65, 59, 102, 79, 66, 118, 29, 43, 164, 253, 13, 228, 108, 106, 252, 230, 45, 237, 12, 149, 152, 235, 143, 178, 102, 199, 227, 65, 230, 178, 140, 133, 93, 213, 89, 41, 198, 197, 215, 94, 122, 58, 18, 251, 179, 187, 61, 1, 239, 229, 179, 214, 244, 97, 202, 42},
        {190, 173, 125, 234, 225, 164, 122, 176, 130, 152, 32, 205, 41, 44, 78, 230, 128, 101, 92, 134, 176, 227, 128, 184, 180, 130, 142, 165, 134, 141, 110, 153, 50, 65, 25, 14, 98, 172, 34, 94, 181, 210, 38, 49, 15, 55, 169, 204, 233, 34, 197, 138, 78, 134, 181, 57, 82, 206},
        {154, 48, 226, 109, 5, 179, 159, 79, 237, 32, 199, 98, 33, 127, 219, 8, 110, 36, 68, 76, 24, 100, 105, 49, 245, 131, 53, 59, 61, 75, 216, 146, 103, 132, 185, 132, 24, 216, 243, 97, 70, 233, 161, 6, 10, 226, 77, 85, 182, 219, 24, 87, 154, 117, 124, 3, 106, 233},
        {101, 12, 238, 213, 120, 140, 44, 51, 196, 68, 201, 121, 36, 108, 200, 161, 56, 97, 123, 115, 237, 146, 54, 164, 141, 59, 232, 60, 60, 36, 85, 169, 129, 61, 49, 75, 21, 19, 49, 124, 195, 252, 63, 207, 153, 125, 144, 60, 39, 141, 117, 232, 96, 5, 162, 38, 187, 80},
        {58, 136, 130, 2, 173, 144, 135, 249, 194, 161, 38, 205, 85, 247, 142, 247, 228, 245, 99, 151, 114, 158, 68, 235, 185, 203, 78, 14, 149, 18, 163, 149, 250, 51, 198, 100, 15, 234, 113, 242, 230, 245, 22, 250, 196, 114, 38, 80, 103, 157, 65, 57, 4, 107, 109, 16, 9, 131},
        {231, 109, 52, 176, 87, 22, 48, 253, 54, 106, 47, 175, 119, 108, 137, 133, 99, 143, 63, 81, 242, 135, 75, 49, 22, 130, 125, 185, 168, 229, 196, 43, 92, 226, 57, 76, 149, 140, 100, 86, 217, 135, 132, 114, 90, 208, 180, 174, 150, 112, 147, 191, 11, 164, 32, 117, 5, 36},
        {197, 18, 114, 255, 50, 100, 185, 124, 218, 88, 190, 215, 41, 191, 206, 138, 120, 5, 243, 244, 111, 223, 137, 234, 221, 169, 43, 39, 143, 82, 41, 137, 149, 2, 84, 3, 143, 219, 88, 107, 118, 9, 200, 15, 221, 43, 131, 249, 253, 37, 40, 189, 116, 164, 225, 126, 177, 188},
        {152, 246, 146, 92, 78, 104, 171, 40, 30, 39, 246, 202, 204, 246, 55, 63, 240, 204, 63, 221, 233, 17, 105, 240, 166, 128, 153, 215, 115, 174, 39, 28, 112, 195, 178, 227, 100, 75, 117, 74, 82, 114, 105, 148, 192, 160, 58, 182, 232, 67, 140, 167, 147, 187, 216, 183, 66, 19},
        {88, 233, 3, 20, 252, 51, 135, 113, 130, 146, 84, 13, 81, 30, 147, 99, 56, 10, 63, 185, 42, 166, 207, 88, 220, 165, 199, 7, 86, 27, 71, 58, 216, 213, 113, 126, 19, 45, 56, 108, 143, 26, 252, 120, 123, 185, 143, 39, 153, 166, 78, 151, 33, 124, 208, 125, 40, 233},
        {73, 120, 195, 119, 81, 197, 85, 70, 175, 109, 204, 25, 136, 117, 21, 195, 222, 74, 162, 75, 237, 9, 155, 148, 242, 157, 99, 129, 206, 123, 255, 182, 75, 94, 57, 229, 151, 178, 115, 53, 34, 17, 139, 20, 30, 190, 82, 126, 204, 133, 128, 61, 227, 71, 16, 86, 4, 201},
        {62, 195, 117, 83, 179, 169, 59, 213, 201, 116, 240, 164, 198, 84, 105, 89, 127, 51, 126, 50, 81, 215, 167, 203, 139, 96, 251, 23, 173, 37, 188, 176, 235, 36, 53, 56, 67, 148, 47, 18, 237, 164, 221, 182, 234, 200, 51, 29, 243, 115, 114, 246, 173, 29, 62, 127, 167, 14},
        {169, 67, 240, 110, 142, 45, 20, 35, 20, 206, 92, 117, 106, 151, 17, 35, 2, 94, 255, 101, 84, 49, 101, 168, 17, 122, 73, 59, 87, 175, 103, 105, 140, 56, 62, 64, 5, 220, 188, 80, 138, 214, 246, 235, 11, 222, 227, 230, 54, 55, 52, 88, 237, 16, 238, 237, 27, 194},
        {88, 216, 182, 118, 206, 243, 194, 206, 137, 152, 189, 167, 238, 184, 242, 69, 36, 248, 173, 121, 146, 27, 239, 84, 132, 18, 61, 215, 186, 63, 70, 122, 173, 41, 138, 242, 176, 76, 175, 165, 149, 194, 88, 231, 4, 114, 241, 254, 201, 120, 58, 47, 222, 2, 123, 75, 114, 176},
        {188, 19, 183, 35, 242, 4, 50, 148, 5, 83, 98, 226, 132, 70, 109, 207, 93, 173, 89, 56, 167, 215, 50, 7, 10, 227, 169, 183, 90, 56, 48, 240, 253, 128, 253, 243, 52, 59, 182, 102, 244, 200, 169, 111, 38, 177, 75, 71, 199, 90, 47, 66, 186, 31, 231, 86, 23, 111},
        {23, 55, 128, 7, 36, 174, 140, 216, 161, 135, 112, 142, 248, 244, 169, 173, 126, 229, 219, 233, 3, 40, 112, 29, 130, 246, 246, 170, 182, 54, 85, 154, 76, 227, 6, 219, 121, 94, 24, 81, 142, 202, 226, 212, 231, 55, 200, 225, 62, 28, 217, 96, 242, 50, 143, 249, 1, 118},
        {36, 111, 216, 59, 50, 180, 160, 75, 113, 134, 211, 91, 182, 143, 169, 101, 207, 67, 126, 96, 42, 56, 183, 225, 15, 184, 125, 128, 115, 21, 76, 214, 228, 55, 135, 200, 122, 54, 10, 195, 57, 215, 193, 137, 218, 47, 31, 75, 201, 19, 226, 46, 219, 252, 171, 244, 153, 190},
        {202, 21, 206, 182, 17, 61, 151, 229, 64, 62, 73, 178, 215, 44, 252, 93, 5, 209, 253, 16, 63, 35, 156, 48, 132, 142, 110, 111, 142, 65, 41, 174, 240, 80, 64, 126, 247, 108, 249, 9, 154, 80, 102, 29, 170, 52, 203, 253, 175, 191, 82, 31, 64, 248, 79, 31, 153, 237},
        {63, 144, 241, 65, 93, 237, 185, 69, 251, 58, 85, 58, 152, 193, 129, 101, 152, 224, 102, 114, 197, 80, 147, 168, 161, 35, 37, 176, 37, 19, 150, 140, 126, 239, 31, 84, 110, 203, 7, 62, 79, 48, 27, 101, 153, 52, 2, 110, 203, 86, 143, 164, 144, 196, 194, 80, 87, 17},
        {20, 217, 37, 96, 55, 13, 235, 165, 222, 135, 30, 148, 34, 171, 224, 35, 95, 56, 14, 247, 5, 181, 213, 16, 162, 2, 124, 197, 27, 211, 78, 31, 186, 240, 5, 6, 25, 69, 239, 23, 105, 5, 142, 36, 99, 80, 157, 139, 199, 218, 129, 93, 53, 150, 145, 76, 209, 173},
        {102, 239, 33, 51, 4, 178, 28, 177, 128, 137, 105, 141, 208, 44, 210, 248, 152, 72, 255, 24, 26, 112, 197, 180, 35, 51, 35, 150, 104, 152, 253, 28, 134, 112, 41, 200, 80, 83, 171, 151, 10, 167, 71, 162, 53, 204, 242, 207, 41, 54, 32, 236, 75, 36, 132, 91, 34, 112},
        {230, 225, 186, 12, 73, 187, 104, 52, 239, 137, 241, 251, 194, 35, 227, 12, 21, 251, 1, 210, 178, 186, 187, 212, 199, 45, 72, 126, 86, 110, 94, 159, 88, 238, 94, 182, 143, 236, 43, 42, 34, 71, 81, 29, 120, 105, 177, 144, 178, 120, 255, 94, 193, 145, 44, 236, 247, 141},
        {131, 247, 106, 160, 99, 127, 254, 236, 225, 79, 24, 221, 242, 124, 91, 71, 209, 121, 237, 27, 217, 152, 35, 103, 27, 7, 61, 28, 185, 73, 182, 77, 200, 106, 117, 51, 96, 56, 125, 37, 61, 213, 103, 101, 88, 83, 102, 162, 159, 216, 31, 113, 68, 132, 78, 30, 248, 98},
        {141, 134, 43, 202, 72, 109, 204, 33, 132, 193, 51, 182, 43, 212, 100, 221, 126, 205, 46, 77, 190, 130, 181, 189, 175, 208, 165, 139, 133, 24, 113, 224, 15, 96, 20, 206, 175, 176, 68, 217, 213, 95, 140, 58, 214, 164, 80, 48, 161, 118, 97, 194, 209, 247, 238, 230, 26, 34},
        {214, 148, 137, 44, 243, 55, 191, 63, 77, 214, 201, 75, 217, 156, 103, 212, 104, 128, 241, 41, 83, 85, 83, 182, 214, 56, 127, 110, 57, 214, 249, 25, 236, 146, 192, 92, 101, 119, 184, 14, 83, 139, 28, 130, 232, 139, 88, 56, 204, 204, 150, 58, 197, 3, 51, 115, 171, 240},
        {45, 176, 137, 213, 83, 71, 180, 128, 251, 170, 151, 33, 125, 122, 145, 152, 32, 29, 244, 173, 19, 175, 36, 161, 46, 108, 88, 154, 198, 123, 60, 147, 246, 64, 239, 179, 146, 240, 54, 156, 124, 91, 75, 164, 1, 18, 169, 50, 26, 173, 131, 149, 102, 70, 251, 159, 11, 242},
        {101, 187, 110, 190, 192, 218, 216, 24, 11, 82, 67, 41, 103, 48, 205, 235, 168, 47, 66, 195, 12, 153, 253, 233, 29, 224, 7, 81, 157, 223, 101, 77, 128, 172, 245, 29, 34, 153, 25, 185, 62, 198, 141, 37, 59, 118, 96, 216, 64, 33, 3, 115, 162, 249, 145, 161, 39, 49},
        {94, 206, 2, 170, 252, 165, 52, 243, 243, 102, 47, 226, 182, 51, 212, 93, 231, 98, 241, 134, 172, 160, 3, 137, 198, 160, 51, 66, 153, 220, 86, 62, 128, 24, 198, 71, 126, 233, 228, 243, 31, 158, 125, 24, 203, 239, 228, 59, 74, 135, 132, 63, 183, 76, 5, 9, 143, 167},
        {62, 212, 195, 146, 110, 4, 91, 180, 124, 40, 251, 71, 61, 106, 47, 152, 225, 10, 86, 97, 156, 150, 14, 83, 150, 84, 198, 71, 110, 114, 27, 25, 99, 239, 115, 199, 225, 125, 116, 133, 43, 153, 82, 64, 230, 29, 98, 171, 182, 245, 112, 242, 175, 73, 53, 106, 248, 133},
        {65, 208, 229, 79, 178, 119, 149, 48, 150, 242, 149, 110, 57, 7, 128, 153, 202, 211, 206, 218, 3, 45, 91, 82, 253, 98, 180, 185, 153, 212, 22, 233, 116, 66, 62, 79, 247, 165, 192, 32, 79, 200, 68, 87, 209, 89, 71, 144, 241, 160, 165, 119, 126, 62, 7, 20, 178, 125},
        {66, 194, 199, 72, 30, 167, 104, 8, 188, 230, 72, 45, 18, 64, 35, 84, 64, 224, 143, 99, 244, 77, 194, 171, 115, 86, 200, 40, 205, 185, 128, 199, 14, 197, 255, 61, 184, 242, 31, 99, 85, 216, 129, 3, 72, 182, 211, 150, 26, 45, 164, 63, 218, 97, 181, 182, 26, 172},
        {46, 73, 249, 186, 70, 166, 170, 161, 98, 165, 160, 141, 25, 242, 131, 190, 43, 45, 12, 242, 21, 247, 30, 156, 188, 150, 124, 206, 42, 21, 99, 201, 162, 50, 212, 179, 52, 108, 180, 204, 174, 41, 140, 123, 14, 106, 68, 154, 100, 177, 54, 58, 66, 215, 92, 137, 24, 216},
        {131, 63, 194, 227, 213, 112, 227, 46, 116, 194, 52, 140, 132, 167, 138, 39, 99, 71, 59, 22, 249, 63, 110, 194, 83, 124, 134, 40, 9, 53, 205, 112, 158, 144, 169, 185, 101, 131, 253, 186, 219, 89, 9, 184, 62, 37, 101, 87, 149, 14, 214, 184, 32, 7, 8, 110, 157, 141},
        {42, 239, 135, 195, 81, 125, 136, 127, 58, 211, 123, 157, 75, 107, 154, 100, 161, 46, 157, 58, 123, 179, 20, 189, 215, 98, 69, 18, 175, 20, 175, 11, 27, 127, 17, 177, 82, 77, 58, 140, 53, 23, 43, 11, 64, 33, 1, 163, 115, 59, 46, 114, 185, 216, 43, 233, 30, 109},
        {187, 107, 37, 79, 138, 135, 199, 125, 100, 160, 209, 101, 79, 175, 142, 182, 14, 16, 33, 85, 179, 136, 192, 221, 110, 59, 128, 190, 176, 114, 107, 181, 8, 123, 87, 3, 82, 100, 79, 166, 32, 172, 206, 166, 177, 16, 30, 27, 156, 47, 3, 241, 186, 3, 233, 75, 189, 170},
        {9, 165, 153, 194, 5, 174, 10, 63, 16, 164, 181, 18, 107, 155, 255, 189, 32, 70, 255, 198, 172, 116, 102, 163, 87, 238, 208, 19, 207, 81, 226, 130, 36, 223, 98, 234, 108, 136, 113, 176, 188, 113, 103, 29, 43, 131, 26, 247, 17, 208, 158, 247, 22, 55, 98, 62, 83, 91},
        {122, 218, 243, 230, 181, 240, 78, 230, 125, 90, 141, 63, 181, 72, 34, 163, 211, 215, 3, 128, 106, 59, 113, 131, 158, 208, 182, 227, 2, 45, 162, 58, 49, 199, 209, 30, 40, 232, 161, 64, 126, 69, 193, 153, 253, 55, 57, 194, 77, 251, 139, 85, 136, 246, 82, 129, 112, 108},
        {3, 23, 252, 210, 151, 185, 126, 184, 72, 131, 93, 160, 61, 246, 134, 64, 40, 203, 79, 34, 204, 149, 25, 221, 12, 193, 154, 85, 73, 152, 29, 129, 176, 161, 171, 238, 217, 105, 239, 86, 255, 10, 209, 131, 23, 37, 231, 26, 18, 135, 175, 22, 116, 6, 51, 194, 87, 235},
        {19, 239, 7, 48, 105, 219, 196, 193, 243, 116, 95, 221, 73, 66, 231, 53, 8, 176, 139, 131, 2, 10, 74, 187, 90, 36, 199, 11, 209, 224, 181, 56, 51, 115, 183, 217, 134, 79, 181, 170, 252, 113, 6, 84, 254, 59, 138, 194, 181, 204, 63, 218, 218, 9, 135, 240, 75, 4},
        {118, 105, 33, 252, 158, 172, 57, 215, 1, 102, 65, 97, 114, 123, 228, 46, 77, 159, 175, 112, 2, 78, 135, 37, 128, 188, 73, 95, 136, 97, 211, 225, 153, 170, 208, 55, 32, 27, 122, 127, 162, 200, 171, 237, 182, 165, 230, 222, 31, 80, 218, 186, 33, 56, 95, 30, 193, 34},
        {6, 172, 37, 99, 30, 134, 173, 200, 150, 224, 104, 27, 101, 244, 250, 32, 37, 125, 178, 237, 232, 225, 10, 194, 38, 62, 40, 146, 22, 161, 1, 149, 232, 164, 114, 174, 164, 162, 21, 137, 28, 74, 253, 47, 236, 27, 24, 160, 99, 150, 248, 253, 248, 32, 175, 98, 175, 234},
        {154, 136, 227, 53, 140, 76, 189, 152, 149, 52, 191, 42, 247, 51, 3, 188, 168, 129, 92, 162, 115, 60, 107, 187, 143, 17, 137, 157, 10, 219, 244, 253, 107, 94, 92, 239, 184, 30, 253, 86, 145, 64, 57, 221, 20, 1, 97, 228, 218, 81, 172, 106, 237, 195, 218, 25, 49, 20},
        {14, 142, 223, 89, 178, 180, 186, 230, 37, 21, 217, 61, 213, 111, 83, 33, 88, 216, 192, 230, 12, 2, 136, 41, 188, 132, 163, 107, 195, 180, 59, 177, 232, 241, 187, 138, 165, 223, 243, 87, 177, 4, 57, 80, 43, 195, 13, 36, 232, 89, 143, 255, 208, 27, 118, 64, 9, 126},
        {193, 156, 18, 104, 103, 145, 238, 163, 191, 245, 62, 77, 72, 18, 51, 35, 37, 30, 146, 119, 195, 104, 116, 164, 199, 215, 62, 107, 216, 252, 56, 249, 1, 107, 215, 213, 171, 23, 244, 94, 53, 209, 109, 74, 10, 103, 70, 207, 161, 94, 58, 155, 72, 138, 79, 245, 90, 130},
        {79, 59, 250, 36, 207, 70, 246, 222, 60, 177, 165, 41, 204, 234, 152, 167, 149, 103, 155, 164, 187, 3, 17, 106, 13, 56, 133, 163, 235, 220, 120, 143, 129, 186, 95, 61, 175, 136, 71, 10, 115, 67, 117, 1, 45, 98, 49, 241, 153, 52, 208, 110, 173, 47, 113, 244, 61, 144},
        {251, 48, 41, 161, 98, 4, 23, 58, 118, 137, 248, 53, 112, 216, 84, 215, 230, 30, 47, 192, 128, 172, 163, 224, 153, 32, 247, 171, 185, 250, 215, 122, 108, 176, 103, 100, 88, 226, 193, 41, 242, 37, 192, 195, 80, 138, 188, 51, 47, 149, 155, 136, 53, 252, 19, 64, 193, 142},
        {124, 242, 42, 20, 52, 143, 229, 10, 57, 221, 174, 40, 150, 213, 224, 204, 178, 33, 118, 18, 244, 244, 237, 3, 222, 160, 236, 31, 243, 114, 105, 73, 192, 178, 102, 101, 53, 94, 197, 3, 132, 227, 160, 186, 34, 225, 141, 34, 52, 76, 102, 119, 181, 212, 14, 205, 191, 213},
        {18, 64, 11, 249, 128, 124, 136, 8, 208, 164, 247, 53, 52, 35, 117, 134, 253, 34, 226, 165, 253, 103, 53, 43, 10, 195, 107, 215, 253, 44, 79, 166, 118, 115, 128, 1, 187, 156, 116, 38, 55, 38, 104, 27, 189, 70, 245, 66, 54, 172, 51, 147, 164, 178, 22, 189, 253, 110},
        {186, 131, 99, 220, 159, 82, 188, 47, 130, 235, 80, 242, 18, 26, 119, 140, 149, 68, 174, 53, 227, 91, 10, 152, 118, 211, 236, 58, 19, 86, 67, 191, 40, 102, 127, 135, 84, 178, 104, 78, 20, 130, 120, 219, 219, 165, 194, 5, 198, 44, 83, 108, 68, 100, 192, 6, 80, 203},
        {244, 1, 47, 157, 50, 104, 143, 121, 171, 22, 185, 89, 161, 84, 117, 207, 80, 102, 206, 80, 112, 208, 81, 221, 226, 101, 99, 138, 24, 202, 173, 238, 196, 243, 122, 135, 30, 65, 224, 10, 207, 251, 255, 153, 6, 227, 204, 111, 108, 15, 154, 216, 146, 153, 174, 27, 154, 46},
        {166, 77, 140, 145, 232, 144, 89, 158, 148, 141, 37, 165, 157, 162, 192, 200, 9, 9, 104, 112, 87, 52, 200, 120, 142, 45, 51, 235, 242, 210, 120, 215, 74, 253, 40, 204, 70, 217, 114, 147, 235, 77, 87, 158, 168, 173, 127, 182, 243, 109, 81, 99, 102, 163, 156, 151, 214, 50},
        {235, 88, 105, 58, 29, 99, 50, 220, 211, 227, 31, 24, 23, 181, 195, 94, 74, 2, 153, 222, 56, 121, 105, 55, 131, 212, 174, 111, 223, 208, 196, 124, 12, 40, 90, 94, 6, 220, 75, 174, 126, 71, 86, 38, 60, 251, 12, 123, 23, 235, 46, 225, 213, 196, 219, 254, 253, 173},
        {167, 130, 60, 200, 96, 187, 40, 113, 160, 84, 38, 24, 41, 222, 144, 171, 225, 27, 143, 56, 22, 41, 127, 36, 234, 121, 79, 140, 113, 99, 114, 84, 85, 69, 215, 249, 41, 254, 25, 158, 209, 208, 108, 9, 109, 223, 220, 156, 92, 80, 114, 87, 64, 158, 130, 146, 138, 215},
        {108, 47, 174, 236, 151, 205, 169, 124, 151, 201, 168, 91, 80, 176, 57, 217, 13, 166, 171, 95, 96, 91, 149, 209, 18, 164, 249, 213, 250, 137, 237, 234, 214, 216, 233, 152, 7, 248, 2, 105, 38, 58, 205, 209, 27, 40, 167, 68, 228, 43, 79, 118, 135, 82, 40, 15, 50, 86},
        {41, 109, 177, 142, 47, 51, 187, 195, 198, 206, 119, 44, 158, 252, 67, 181, 212, 88, 228, 139, 126, 213, 82, 234, 75, 124, 215, 142, 248, 125, 35, 8, 11, 167, 53, 206, 180, 110, 70, 132, 89, 158, 220, 141, 167, 220, 220, 66, 176, 128, 95, 118, 86, 241, 187, 89, 169, 89},
        {19, 197, 125, 125, 53, 99, 78, 4, 136, 250, 18, 247, 197, 225, 237, 240, 253, 76, 24, 40, 171, 184, 10, 240, 109, 99, 122, 70, 10, 81, 80, 6, 186, 200, 177, 71, 166, 34, 178, 3, 46, 215, 146, 89, 240, 139, 115, 249, 237, 110, 56, 42, 186, 43, 112, 120, 208, 250},
        {76, 132, 133, 106, 171, 24, 138, 136, 53, 120, 173, 40, 116, 36, 165, 27, 205, 167, 81, 15, 168, 148, 227, 184, 214, 205, 123, 4, 108, 148, 229, 196, 244, 145, 144, 100, 250, 196, 117, 187, 145, 44, 231, 188, 176, 64, 13, 231, 127, 178, 180, 241, 61, 83, 21, 91, 102, 129},
        {48, 210, 222, 175, 41, 107, 16, 81, 186, 110, 8, 71, 8, 48, 88, 203, 67, 80, 210, 123, 187, 227, 142, 241, 160, 79, 25, 237, 118, 57, 179, 239, 140, 1, 31, 71, 136, 158, 180, 190, 132, 130, 153, 179, 180, 177, 193, 7, 102, 67, 155, 145, 219, 53, 159, 224, 186, 35},
        {42, 92, 106, 223, 29, 129, 147, 140, 69, 29, 215, 161, 128, 231, 13, 182, 77, 14, 138, 211, 22, 241, 200, 93, 228, 145, 118, 141, 106, 107, 163, 117, 132, 109, 128, 7, 172, 160, 39, 197, 49, 72, 240, 155, 75, 171, 149, 7, 35, 200, 99, 63, 144, 35, 25, 126, 144, 74},
        {208, 233, 31, 47, 4, 122, 82, 145, 161, 246, 27, 245, 202, 177, 213, 121, 8, 131, 31, 207, 85, 30, 100, 142, 53, 205, 170, 102, 118, 16, 234, 141, 112, 36, 21, 182, 63, 246, 166, 158, 44, 135, 62, 122, 72, 187, 234, 187, 70, 199, 128, 31, 122, 67, 112, 185, 130, 81}};

    auto rs = std::make_unique<ReedSolomon>(nroots, minpoly, prim, fcr, pad, shortening, genpoly_coeff, genmatrix);

    std::vector<uint8_t> encoded_output = rs->encode_with_generator_matrix(information_vector);

    EXPECT_TRUE(code_vector == encoded_output);
}


TEST(ReedSolomonE1BTest, DecodeNoErrors)
{
    // ICD 2.0 Annex F
    const std::vector<uint8_t> information_vector = {147, 109, 66, 23, 234, 140,
        74, 234, 49, 89, 241, 253, 169, 161, 89, 93, 75, 142, 83, 102, 98, 218,
        14, 197, 155, 151, 43, 181, 9, 163, 142, 111, 8, 118, 21, 47, 135, 139,
        108, 215, 51, 147, 185, 52, 17, 151, 97, 102, 238, 71, 83, 114, 47, 80,
        67, 199, 215, 162};

    std::vector<uint8_t> code_vector = {147, 109, 66, 23, 234, 140, 74, 234, 49,
        89, 241, 253, 169, 161, 89, 93, 75, 142, 83, 102, 98, 218, 14, 197, 155,
        151, 43, 181, 9, 163, 142, 111, 8, 118, 21, 47, 135, 139, 108, 215, 51,
        147, 185, 52, 17, 151, 97, 102, 238, 71, 83, 114, 47, 80, 67, 199, 215,
        162, 238, 77, 12, 72, 235, 21, 148, 213, 230, 54, 183, 82, 49, 104, 12,
        228, 150, 157, 220, 112, 236, 187, 63, 31, 175, 47, 210, 164, 17, 104,
        98, 46, 252, 165, 194, 57, 26, 213, 14, 133, 176, 148, 34, 9, 167, 43,
        204, 198, 25, 164, 233, 55, 153, 31, 237, 84, 212, 76, 137, 242};

    // Instantiate a ReedSolomon object with Galileo E1 (INAV) parameters
    const int nroots = 60;
    const int minpoly = 29;
    const int prim = 1;
    const int fcr = 195;
    const int pad = 0;
    const int shortening = 137;
    auto rs = std::make_unique<ReedSolomon>(nroots, minpoly, prim, fcr, pad, shortening);

    int result = rs->decode(code_vector);

    EXPECT_TRUE(result == 0);

    std::vector<uint8_t> decoded(code_vector.begin(), code_vector.begin() + 58);

    EXPECT_TRUE(information_vector == decoded);
}


TEST(ReedSolomonE1BTest, Decode30Errors)
{
    // ICD 2.0 Annex F
    const std::vector<uint8_t> information_vector = {147, 109, 66, 23, 234, 140,
        74, 234, 49, 89, 241, 253, 169, 161, 89, 93, 75, 142, 83, 102, 98, 218,
        14, 197, 155, 151, 43, 181, 9, 163, 142, 111, 8, 118, 21, 47, 135, 139,
        108, 215, 51, 147, 185, 52, 17, 151, 97, 102, 238, 71, 83, 114, 47, 80,
        67, 199, 215, 162};

    std::vector<uint8_t> code_vector = {147, 109, 66, 23, 234, 140, 74, 234, 49,
        89, 241, 253, 169, 161, 89, 93, 75, 142, 83, 102, 98, 218, 14, 197, 155,
        151, 43, 181, 9, 163, 142, 111, 8, 118, 21, 47, 135, 139, 108, 215, 51,
        147, 185, 52, 17, 151, 97, 102, 238, 71, 83, 114, 47, 80, 67, 199, 215,
        162, 238, 77, 12, 72, 235, 21, 148, 213, 230, 54, 183, 82, 49, 104, 12,
        228, 150, 157, 220, 112, 236, 187, 63, 31, 175, 47, 210, 164, 17, 104,
        98, 46, 252, 165, 194, 57, 26, 213, 14, 133, 176, 148, 34, 9, 167, 43,
        204, 198, 25, 164, 233, 55, 153, 31, 237, 84, 212, 76, 137, 242};

    // Introduce 30 non-consecutive errors
    for (int i = 0; i < 60; i += 2)
        {
            code_vector[i] = 0;
        }

    auto rs = std::make_unique<ReedSolomon>("E1B");

    int result = rs->decode(code_vector);

    EXPECT_TRUE(result == 30);

    std::vector<uint8_t> decoded(code_vector.begin(), code_vector.begin() + 58);

    EXPECT_TRUE(information_vector == decoded);
}


TEST(ReedSolomonE1BTest, Decode31Errors)
{
    // ICD 2.0 Annex F
    const std::vector<uint8_t> information_vector = {147, 109, 66, 23, 234, 140,
        74, 234, 49, 89, 241, 253, 169, 161, 89, 93, 75, 142, 83, 102, 98, 218,
        14, 197, 155, 151, 43, 181, 9, 163, 142, 111, 8, 118, 21, 47, 135, 139,
        108, 215, 51, 147, 185, 52, 17, 151, 97, 102, 238, 71, 83, 114, 47, 80,
        67, 199, 215, 162};

    std::vector<uint8_t> code_vector = {147, 109, 66, 23, 234, 140, 74, 234, 49,
        89, 241, 253, 169, 161, 89, 93, 75, 142, 83, 102, 98, 218, 14, 197, 155,
        151, 43, 181, 9, 163, 142, 111, 8, 118, 21, 47, 135, 139, 108, 215, 51,
        147, 185, 52, 17, 151, 97, 102, 238, 71, 83, 114, 47, 80, 67, 199, 215,
        162, 238, 77, 12, 72, 235, 21, 148, 213, 230, 54, 183, 82, 49, 104, 12,
        228, 150, 157, 220, 112, 236, 187, 63, 31, 175, 47, 210, 164, 17, 104,
        98, 46, 252, 165, 194, 57, 26, 213, 14, 133, 176, 148, 34, 9, 167, 43,
        204, 198, 25, 164, 233, 55, 153, 31, 237, 84, 212, 76, 137, 242};

    // Introduce 31 errors (this should make the decoder to fail)
    for (int i = 0; i < 62; i += 2)
        {
            code_vector[i] = 0;
        }

    auto rs = std::make_unique<ReedSolomon>("E1B");

    int result = rs->decode(code_vector);

    EXPECT_TRUE(result == -1);
}


TEST(ReedSolomonE1BTest, DecodeErasureCorrectionCase1)
{
    // ICD 2.0 Annex F
    const std::vector<uint8_t> information_vector = {147, 109, 66, 23, 234, 140,
        74, 234, 49, 89, 241, 253, 169, 161, 89, 93, 75, 142, 83, 102, 98, 218,
        14, 197, 155, 151, 43, 181, 9, 163, 142, 111, 8, 118, 21, 47, 135, 139,
        108, 215, 51, 147, 185, 52, 17, 151, 97, 102, 238, 71, 83, 114, 47, 80,
        67, 199, 215, 162};

    std::vector<uint8_t> code_vector = {147, 109, 66, 23, 234, 140, 74, 234, 49,
        89, 241, 253, 169, 161, 89, 93, 75, 142, 83, 102, 98, 218, 14, 197, 155,
        151, 43, 181, 9, 163, 142, 111, 8, 118, 21, 47, 135, 139, 108, 215, 51,
        147, 185, 52, 17, 151, 97, 102, 238, 71, 83, 114, 47, 80, 67, 199, 215,
        162, 238, 77, 12, 72, 235, 21, 148, 213, 230, 54, 183, 82, 49, 104, 12,
        228, 150, 157, 220, 112, 236, 187, 63, 31, 175, 47, 210, 164, 17, 104,
        98, 46, 252, 165, 194, 57, 26, 213, 14, 133, 176, 148, 34, 9, 167, 43,
        204, 198, 25, 164, 233, 55, 153, 31, 237, 84, 212, 76, 137, 242};

    std::vector<int> erasure_positions;
    erasure_positions.reserve(60);  // nroots is the maximum number of erasure positions

    // We have received Word 2, Word 4, Word 18, Word 20
    // So we have: c_1, c_3, g_1, g_3

    // Delete c_0
    // We always know c_{0,0}, so we start at 1
    for (int i = 1; i < 16; i++)
        {
            code_vector[i] = 0;
            erasure_positions.push_back(i);
        }

    // Delete c_2
    for (int i = 30; i < 44; i++)
        {
            code_vector[i] = 0;
            erasure_positions.push_back(i);
        }

    // Delete g_0
    for (int i = 58; i < 73; i++)
        {
            code_vector[i] = 0;
            erasure_positions.push_back(i + 137);  // erasure position refers to the unshortened code, so we add 137
        }

    // Delete g_2
    for (int i = 88; i < 103; i++)
        {
            code_vector[i] = 0;
            erasure_positions.push_back(i + 137);
        }

    auto rs = std::make_unique<ReedSolomon>("E1B");

    int result = rs->decode(code_vector, erasure_positions);

    EXPECT_TRUE(result == 59);

    std::vector<uint8_t> decoded(code_vector.begin(), code_vector.begin() + 58);

    EXPECT_TRUE(information_vector == decoded);
}


TEST(ReedSolomonE1BTest, DecodeErasureCorrectionCase2)
{
    // ICD 2.0 Annex F
    const std::vector<uint8_t> information_vector = {147, 109, 66, 23, 234, 140,
        74, 234, 49, 89, 241, 253, 169, 161, 89, 93, 75, 142, 83, 102, 98, 218,
        14, 197, 155, 151, 43, 181, 9, 163, 142, 111, 8, 118, 21, 47, 135, 139,
        108, 215, 51, 147, 185, 52, 17, 151, 97, 102, 238, 71, 83, 114, 47, 80,
        67, 199, 215, 162};

    std::vector<uint8_t> code_vector = {147, 109, 66, 23, 234, 140, 74, 234, 49,
        89, 241, 253, 169, 161, 89, 93, 75, 142, 83, 102, 98, 218, 14, 197, 155,
        151, 43, 181, 9, 163, 142, 111, 8, 118, 21, 47, 135, 139, 108, 215, 51,
        147, 185, 52, 17, 151, 97, 102, 238, 71, 83, 114, 47, 80, 67, 199, 215,
        162, 238, 77, 12, 72, 235, 21, 148, 213, 230, 54, 183, 82, 49, 104, 12,
        228, 150, 157, 220, 112, 236, 187, 63, 31, 175, 47, 210, 164, 17, 104,
        98, 46, 252, 165, 194, 57, 26, 213, 14, 133, 176, 148, 34, 9, 167, 43,
        204, 198, 25, 164, 233, 55, 153, 31, 237, 84, 212, 76, 137, 242};

    std::vector<int> erasure_positions;
    erasure_positions.reserve(60);  // nroots is the maximum number of erasure positions

    // We have received Word 2, Word 4, Word 17, Word 19
    // So we have: c_1, c_3, g_0, g_2

    // Delete c_0
    // We always know c_{0,0}, so we start at 1
    for (int i = 1; i < 16; i++)
        {
            code_vector[i] = 0;
            erasure_positions.push_back(i);
        }

    // Delete c_2
    for (int i = 30; i < 44; i++)
        {
            code_vector[i] = 0;
            erasure_positions.push_back(i);
        }

    // Delete g_1
    for (int i = 73; i < 88; i++)
        {
            code_vector[i] = 0;
            erasure_positions.push_back(i + 137);  // erasure position refers to the unshortened code, so we add 137
        }

    // Delete g_3
    for (int i = 103; i < 118; i++)
        {
            code_vector[i] = 0;
            erasure_positions.push_back(i + 137);
        }

    auto rs = std::make_unique<ReedSolomon>("E1B");

    int result = rs->decode(code_vector, erasure_positions);

    EXPECT_TRUE(result == 59);

    std::vector<uint8_t> decoded(code_vector.begin(), code_vector.begin() + 58);

    EXPECT_TRUE(information_vector == decoded);
}


TEST(ReedSolomonE1BTest, DecodeErasureCorrectionCase3)
{
    // ICD 2.0 Annex F
    const std::vector<uint8_t> information_vector = {147, 109, 66, 23, 234, 140,
        74, 234, 49, 89, 241, 253, 169, 161, 89, 93, 75, 142, 83, 102, 98, 218,
        14, 197, 155, 151, 43, 181, 9, 163, 142, 111, 8, 118, 21, 47, 135, 139,
        108, 215, 51, 147, 185, 52, 17, 151, 97, 102, 238, 71, 83, 114, 47, 80,
        67, 199, 215, 162};

    std::vector<uint8_t> code_vector = {147, 109, 66, 23, 234, 140, 74, 234, 49,
        89, 241, 253, 169, 161, 89, 93, 75, 142, 83, 102, 98, 218, 14, 197, 155,
        151, 43, 181, 9, 163, 142, 111, 8, 118, 21, 47, 135, 139, 108, 215, 51,
        147, 185, 52, 17, 151, 97, 102, 238, 71, 83, 114, 47, 80, 67, 199, 215,
        162, 238, 77, 12, 72, 235, 21, 148, 213, 230, 54, 183, 82, 49, 104, 12,
        228, 150, 157, 220, 112, 236, 187, 63, 31, 175, 47, 210, 164, 17, 104,
        98, 46, 252, 165, 194, 57, 26, 213, 14, 133, 176, 148, 34, 9, 167, 43,
        204, 198, 25, 164, 233, 55, 153, 31, 237, 84, 212, 76, 137, 242};

    std::vector<int> erasure_positions;
    erasure_positions.reserve(60);  // nroots is the maximum number of erasure positions

    // We have received Word 1, Word 3, Word 17, Word 19
    // So we have: c_0, c_2, g_0, g_2

    // Delete c_1
    for (int i = 16; i < 30; i++)
        {
            code_vector[i] = 0;
            erasure_positions.push_back(i);
        }

    // Delete c_3
    for (int i = 44; i < 58; i++)
        {
            code_vector[i] = 0;
            erasure_positions.push_back(i);
        }

    // Delete g_1
    for (int i = 73; i < 88; i++)
        {
            code_vector[i] = 0;
            erasure_positions.push_back(i + 137);  // erasure position refers to the unshortened code, so we add 137
        }

    // Delete g_3
    for (int i = 103; i < 118; i++)
        {
            code_vector[i] = 0;
            erasure_positions.push_back(i + 137);
        }

    auto rs = std::make_unique<ReedSolomon>("E1B");

    int result = rs->decode(code_vector, erasure_positions);

    EXPECT_TRUE(result == 58);

    std::vector<uint8_t> decoded(code_vector.begin(), code_vector.begin() + 58);

    EXPECT_TRUE(information_vector == decoded);
}


TEST(ReedSolomonE1BTest, DecodeErasureCorrectionCase4)
{
    // ICD 2.0 Annex F
    const std::vector<uint8_t> information_vector = {147, 109, 66, 23, 234, 140,
        74, 234, 49, 89, 241, 253, 169, 161, 89, 93, 75, 142, 83, 102, 98, 218,
        14, 197, 155, 151, 43, 181, 9, 163, 142, 111, 8, 118, 21, 47, 135, 139,
        108, 215, 51, 147, 185, 52, 17, 151, 97, 102, 238, 71, 83, 114, 47, 80,
        67, 199, 215, 162};

    std::vector<uint8_t> code_vector = {147, 109, 66, 23, 234, 140, 74, 234, 49,
        89, 241, 253, 169, 161, 89, 93, 75, 142, 83, 102, 98, 218, 14, 197, 155,
        151, 43, 181, 9, 163, 142, 111, 8, 118, 21, 47, 135, 139, 108, 215, 51,
        147, 185, 52, 17, 151, 97, 102, 238, 71, 83, 114, 47, 80, 67, 199, 215,
        162, 238, 77, 12, 72, 235, 21, 148, 213, 230, 54, 183, 82, 49, 104, 12,
        228, 150, 157, 220, 112, 236, 187, 63, 31, 175, 47, 210, 164, 17, 104,
        98, 46, 252, 165, 194, 57, 26, 213, 14, 133, 176, 148, 34, 9, 167, 43,
        204, 198, 25, 164, 233, 55, 153, 31, 237, 84, 212, 76, 137, 242};

    std::vector<int> erasure_positions;
    erasure_positions.reserve(60);  // nroots is the maximum number of erasure positions

    // We have received Word 1, Word 3, Word 18, Word 20
    // So we have: c_0, c_2, g_1, g_3

    // Delete c_1
    for (int i = 16; i < 30; i++)
        {
            code_vector[i] = 0;
            erasure_positions.push_back(i);
        }

    // Delete c_3
    for (int i = 44; i < 58; i++)
        {
            code_vector[i] = 0;
            erasure_positions.push_back(i);
        }

    // Delete g_0
    for (int i = 58; i < 73; i++)
        {
            code_vector[i] = 0;
            erasure_positions.push_back(i + 137);  // erasure position refers to the unshortened code, so we add 137
        }

    // Delete g_2
    for (int i = 88; i < 103; i++)
        {
            code_vector[i] = 0;
            erasure_positions.push_back(i + 137);
        }

    auto rs = std::make_unique<ReedSolomon>("E1B");

    int result = rs->decode(code_vector, erasure_positions);

    EXPECT_TRUE(result == 58);

    std::vector<uint8_t> decoded(code_vector.begin(), code_vector.begin() + 58);

    EXPECT_TRUE(information_vector == decoded);
}
